import data

def preproc_line(line):
    line = line.strip()
    startIndex = line.index('(')
    endIndex = line.index(')')
    if endIndex != len(line):
        print("warning: there are elements after the ), you need to check.")
    
    if startIndex >= endIndex:
        print("error: the ) is before (.")
        return "", False

    new_line = line[startIndex + 1:  endIndex]
    if len(new_line) == 0:
        print("error: no elements")
        return "", False
    return new_line, True


def parse_loop(line, ops):
    line, flag = preproc_line(line)
    if not flag: 
        return False
    params = line.split(',')
    paramLen = len(params)
    if (paramLen != 3):
        print("loop needs 3 params, now len is ", paramLen)
        return False
    lopOp = data.LoopOp(params[0].strip(), params[1].strip(), params[2].strip())
    ops.append(lopOp)
    return True


def check_param_ifop(line):
    params = line.split()
    strip_params = []
    for e in params:
        ele = e.strip()
        if len(ele) == 0:
            continue
        strip_params.append(ele)

    if not len(strip_params) == 3:
        print("element count is not 3.please make sure.")
        return [], False 
    return strip_params, True


def parse_if(line, ops):
    line, flag = preproc_line(line)
    if not flag:
        return False

    params, flag = check_param_ifop(line)
    ifOp = data.IfOp(params[0], params[1], params[2])
    ops.append(ifOp)
    return True


def parse_elif(line, ops):
    elifOp = data.ElifOp()
    ops.append(elifOp)
    return True


def parse_var(line, ops):
    line, flag = preproc_line(line)
    if not flag:
        return False
    params = line.split(',')
    for param in params:
        param = param.strip()
        if len(param) == 0:
            print("Error: there is empy str before ','")
            return False
    if not len(params) == 2:
        print("var op only needs 2 params, now params count is %d" % (len(params)))
        return False
    
    varOp = data.VarOp(params[0].strip(), params[1].strip())
    varOp.complete = True
    if len(ops) > 0:
        if ops[-1].complete == False:
            ops[-1].stat.append(varOp)
            return True
    ops.append(varOp)
    return True


def parse_defmacro(line, funcs):
    startIndex = line.index('(')
    endIndex = line.index(')')
    func_name = line[:startIndex]
    strDeclar = line[startIndex + 1 : endIndex]
    params = strDeclar.split(',')
    new_params = [e.strip() for e in params]
    func = data.Func(func_name.strip(), new_params)
    funcs.append(func)


def parse_endif(line, ops):
    assert(len(ops) > 0, r"there is no #if or #else_if before #endif")
    assert(ops[-1].OpType == data.Type.IF or ops[-1].OpType() == data.Type.ELIF, 
           r"there is no #if or #else_if before #endif")

    elif_op = data.ElifOp()
    if ops[-1].OpType() == data.Type.ELIF:
        ops[-1].complete = True
        elif_op = ops[-1]
        ops.pop()
    
    assert(ops[-1].OpType == data.Type.IF, r"there is no #if before #endif")
    if len(elif_op.stat) > 0:
        ops[-1].elif_op = elif_op
    ops[-1].complete = True

    if len(ops) > 1:
        if ops[-2].complete == False:
            ops[-2].stat.append(ops[-1])
            ops.pop()
    return True


def parse_endloop(line, ops):
    assert(len(ops) > 0, r"there is no #if before #endif")
    assert(ops[-1].OpType == data.Type.LOOP, r"there is no #loop before #end_loop")
    ops[-1].complete = True

    if len(ops) > 1:
        if ops[-2].complete == False:
            ops[-2].stat.append(ops[-1])
            ops.pop()
    return True


def parse_endmacro(fp, ops):
    return True


def parse_macro(line, ops):
    start_index = line.index('(')
    end_index = line.index(')')
    macro_name = line[:start_index]
    strParms = line[start_index + 1 : end_index]
    params = strParms.split(',')
    new_params = [e.strip() for e in params]
    macroOp = data.MacroOp(macro_name.strip(), new_params)
    macroOp.complete = True
    if ops[-1].complete == False:
        ops[-1].stat.append(macroOp)
    else:
        ops.append(macroOp)
    return True

